package store.lunangangster.engine.impl.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import store.lunangangster.engine.ProcessEngineConfiguration;
import store.lunangangster.engine.impl.Context;
import store.lunangangster.engine.impl.cmd.Command;

/**
 * 该拦截器会拦截即将执行的命令，判断其是否有相应的{@link CommandContext}对象在上下文中。如果没有，
 * 则会创建CommandContext，并加入到上下文中。
 *
 * <p>当所有拦截器执行完成并且命令完成之后，会删除相应的CommandContext
 *
 * @author cwk
 * @version 1.0
 */
public class CommandContextInterceptor implements CommandInterceptor {

  private static final Logger log = LoggerFactory.getLogger(CommandContextInterceptor.class);

  protected CommandInterceptor next;

  public CommandContextInterceptor() {
  }

  public CommandContextInterceptor(CommandInterceptor next) {
    this.next = next;
  }

  @Override
  public <T> T execute(Command<T> command) {
    CommandContext commandContext = Context.getCommandContext();
    ProcessEngineConfiguration processEngineConfiguration = Context.getProcessEngineConfiguration();
    if (commandContext == null) {
      commandContext = new CommandContext(processEngineConfiguration, command);
      Context.setCommandContext(commandContext);
      log.debug("CommandContext创建: 用于命令{}", command);
    }

    try {
      return next.execute(command);
    } catch (Throwable e) {
      commandContext.exception(e);
    } finally {
      try {
        // 关闭CommandContext
        commandContext.close();
        log.debug("CommandContext销毁: 用于命令{}", command);
      } finally {
        Context.removeCommandContext();
      }
    }

    return null;
  }

  @Override
  public CommandInterceptor next() {
    return next;
  }

  @Override
  public void setNext(CommandInterceptor nextInterceptor) {
    next = nextInterceptor;
  }
}
